﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WPFSample.ChooseFontSample
{
    class TextBoxWithLister : ContentControl
    {
        TextBox txtbox;
        Lister lister;

        public event EventHandler SelectionChanged;

        protected virtual void OnSelectionChanged(EventArgs args)
        {
            if (this.SelectionChanged != null)
            {
                this.SelectionChanged(this, args);
            }
        }

        public event TextChangedEventHandler TextChanged;

        void TextBoxOnTextChanged(object sender, TextChangedEventArgs args)
        {
            if (this.TextChanged != null)
            {
                this.TextChanged(this, args);
            }
        }

        private bool isReadOnly;

        public bool IsReadOnly
        {
            get { return isReadOnly; }
            set { isReadOnly = value; }
        }

        public TextBoxWithLister()
        {
            DockPanel dock = new DockPanel();
            this.Content = dock;

            this.txtbox = new TextBox();
            this.txtbox.TextChanged += this.TextBoxOnTextChanged;
            dock.Children.Add(this.txtbox);
            DockPanel.SetDock(this.txtbox, Dock.Top);

            this.lister = new Lister();
            this.lister.SelectionChanged += this.ListerOnSelectionChanged;
            dock.Children.Add(this.lister);
        }

        public string Text
        {
            get
            {
                return this.txtbox.Text;
            }

            set { this.txtbox.Text = value; }
        }

        public object SelectedItem
        {
            get
            {
                return this.lister.SelectedItem;
            }

            set
            {
                this.lister.SelectedItem = value;
                if (this.lister.SelectedItem != null)
                {
                    this.txtbox.Text = this.lister.SelectedItem.ToString();
                }
                else
                {
                    this.txtbox.Text = string.Empty;
                }
            }
        }

        public int SelectedIndex
        {
            set
            {
                this.lister.SelectedIndex = value;
                if (this.lister.SelectedIndex == -1)
                {
                    this.txtbox.Text = string.Empty;
                }
                else
                {
                    this.txtbox.Text = this.lister.SelectedItem.ToString();
                }
            }

            get
            {
                return this.lister.SelectedIndex;
            }
        }

        public void Add(object obj)
        {
            this.lister.Add(obj);
        }

        public void Insert(int index, object obj)
        {
            this.lister.Insert(index, obj);
        }

        public void Clear()
        {
            this.lister.Clear();
        }

        public bool Contains(object obj)
        {
            return this.lister.Contains(obj);
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            this.Focus();
        }

        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
        {
            base.OnGotKeyboardFocus(e);
            if (e.NewFocus == this)
            {
                this.txtbox.Focus();
                if (this.SelectedIndex == -1 && this.lister.Count > 0)
                {
                    this.SelectedIndex = 0;
                }
            }
        }

        protected override void OnPreviewTextInput(TextCompositionEventArgs e)
        {
            base.OnPreviewTextInput(e);
            if (this.IsReadOnly)
            {
                this.lister.GoToLetter(e.Text[0]);
                e.Handled = true;
            }
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            base.OnPreviewKeyDown(e);
            if (this.SelectedIndex == -1)
            {
                return;
            }

            switch (e.Key)
            {
                case Key.Home:
                    if (this.lister.Count > 0)
                    {
                        this.SelectedIndex = 0;
                    }

                    break;
                case Key.End:
                    if (this.lister.Count > 0)
                    {
                        this.SelectedIndex = this.lister.Count - 1;
                    }

                    break;
                case Key.Up:
                    if (this.SelectedIndex > 0)
                    {
                        this.SelectedIndex--;
                    }

                    break;
                case Key.Down:
                    if (this.SelectedIndex < this.lister.Count - 1)
                    {
                        this.SelectedIndex++;
                    }

                    break;
                case Key.PageUp:
                    this.lister.PageUp();
                    break;
                case Key.PageDown:
                    this.lister.PageDown();
                    break;
                default:
                    return;
            }

            e.Handled = true;
        }

        private void ListerOnSelectionChanged(object sender, EventArgs e)
        {
            if (this.SelectedIndex == -1)
            {
                this.txtbox.Text = string.Empty;
            }
            else
            {
                this.txtbox.Text = this.lister.SelectedItem.ToString();
            }

            this.OnSelectionChanged(e);
        }
    }
}
